// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license


// MaterialPreviewWnd.cpp : implementation file
//

#include "stdafx.h"
#include "WorldBuilder.h"
#include "MaterialPreviewWnd.h"
#include "GL.h"
#include "Material.h"


// CMaterialPreviewWnd

IMPLEMENT_DYNAMIC(CMaterialPreviewWnd, CWnd)

CMaterialPreviewWnd::CMaterialPreviewWnd()
:   UiFollower(UiFollower::IsSelectionListener),
    WorldFollower(WorldFollower::ListenNothing)
{
    m_strWndClass = AfxRegisterWndClass(
        CS_DBLCLKS, AfxGetApp()->LoadCursor(IDC_ARROW),
        NULL, NULL);
}

CMaterialPreviewWnd::~CMaterialPreviewWnd()
{
}


// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

void CMaterialPreviewWnd::OnSize(UINT nType, int cx, int cy) 
{
    CWnd::OnSize(nType, cx, cy);
    
    MakeCurrent();
    glViewport(0, 0, cx, cy == 0 ? 1 : cy);

    m_projValid = false;
}

void CMaterialPreviewWnd::OnPaint()
{
    CPaintDC dc(this);

    MakeCurrent();

    if(!m_projValid)
    {
        m_projValid = true;

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        CRect rc;
        GetClientRect(rc);
        double aspect = double(rc.Width()) / rc.Height();
        double zoom = 2.;

        if(rc.Width() > rc.Height())
        {
            glOrtho(-zoom * aspect, zoom * aspect, -zoom , zoom, -100., 100.);
        }
        else
        {
            glOrtho(-zoom, zoom, -zoom / aspect, zoom / aspect, -100., 100.);
        }
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // ------------------------------------------------

    Selectable* selection = getUi().getSelectionManager().getSelection();
    if(Material* mat = dynamic_cast<Material*>(selection))
    {
        mat->setInRenderContext();
        glutSolidSphere(1., 20, 20);
        mat->restoreRenderContext();
    }

    // ------------------------------------------------

    SwapBuffers(GetDC()->m_hDC);
}


// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

void CMaterialPreviewWnd::onSelectionChanged(SelectionManager* /*sender*/)
{
    Invalidate();
}

// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -


BOOL CMaterialPreviewWnd::OnEraseBkgnd(CDC* /*pDC*/)
{
    return FALSE;
}

// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

void CMaterialPreviewWnd::MakeCurrent()
{
    ::wglMakeCurrent(GetDC()->m_hDC, m_hRC);
}

BOOL CMaterialPreviewWnd::Create(DWORD dwStyle, const RECT& rect,
            CWnd* pParentWnd, UINT nID)
{
    return CWnd::Create(m_strWndClass, NULL, dwStyle, 
                        rect, pParentWnd, nID);
}

int CMaterialPreviewWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (__super::OnCreate(lpCreateStruct) == -1)
        return -1;

    bool ok = ::SetupPixelFormat(GetDC());
    VERIFY(ok);
    m_hRC = wglCreateContext(GetDC()->m_hDC);
    VERIFY(m_hRC);
    MakeCurrent();

    glDisable(GL_DEPTH_TEST);

    glClearColor(0., 0., 0., 1.);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    Color ambient(.2f, .2f, .2f);
    Color diffuse(.8f, .8f, .8f);
    Color specular(ColorIds::Grey192);
    
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient.to_array());
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse.to_array());
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular.to_array());

    float dir[] = { -1.f, 0, 1, 0 };
    glLightfv(GL_LIGHT0, GL_POSITION, dir);

    glShadeModel(GL_SMOOTH);

    return 0;
}

void CMaterialPreviewWnd::OnClose() 
{
    MakeCurrent();
    wglDeleteContext(m_hRC);
    CWnd::OnClose();
}

// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

BEGIN_MESSAGE_MAP(CMaterialPreviewWnd, CWnd)
    ON_WM_ERASEBKGND()
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_PAINT()
END_MESSAGE_MAP()
